/*
 * cAesObjImpl_F.cpp
 *
 *  Created on: 2014年10月28日
 *      Author: finder
 */

#include "caes_obj_impl_f.h"


static const unsigned char S_Box[16][16] = {  //S-盒
/***			0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F  ***/
/* 0 */		{0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76},
/* 1 */		{0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0},
/* 2 */		{0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15},
/* 3 */		{0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75},
/* 4 */		{0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84},
/* 5 */		{0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf},
/* 6 */		{0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8},
/* 7 */		{0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2},
/* 8 */		{0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73},
/* 9 */		{0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb},
/* A */		{0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79},
/* B */		{0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08},
/* C */		{0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a},
/* D */		{0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e},
/* E */		{0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf},
/* F */		{0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}};


static const unsigned char inv_S_Box[16][16] = {  //逆S-盒
/***			0     1     2     3     4     5     6     7     8     9     A     B     C     D     E     F  ***/
/* 0 */		{0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb},
/* 1 */		{0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb},
/* 2 */		{0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e},
/* 3 */		{0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25},
/* 4 */		{0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92},
/* 5 */		{0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84},
/* 6 */		{0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06},
/* 7 */		{0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b},
/* 8 */		{0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73},
/* 9 */		{0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e},
/* A */		{0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b},
/* B */		{0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4},
/* C */		{0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f},
/* D */		{0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef},
/* E */		{0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61},
/* F */		{0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}};



//轮常数(ci-0, 00, 00, 00)的ci-0
static const unsigned char Rcon[55] = {0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
								0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6,
								0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91,
								0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a,
								0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb,
								0x8d, 0x01};





static void KeyExpansion(PAES_OPERATOR_t aes);

static unsigned char mul(unsigned char a, unsigned char b) //在GF(2^8)上的乘运算
{
    unsigned char ret = 0;

    for (int i = 0; i < 8; ++i) {
        if (b & 0x01)
            ret ^= a;
        if (a & 0x80) {
            a <<= 1;
            a ^= 0x1B;
        } else
            a <<= 1;
        b >>= 1;
    }
	return ret;
}

static unsigned char sBox(const unsigned char input) //计算字节input经S-Box变换的结果
{
	unsigned char low = input & 0x0F;
	unsigned char hign = (input>>4) & 0x0F;
	return S_Box[hign][low];
}

static unsigned char inv_sBox(const unsigned char input) //计算字节input经逆S-Box变换的结果
{
	unsigned char low = input & 0x0F;
	unsigned char hign = (input>>4) & 0x0F;
	return inv_S_Box[hign][low];
}

static void KeyExpansion(PAES_OPERATOR_t aes)
{
	int j;

	unsigned char (*w)[120] = aes->w;
	unsigned char * Key = aes->Key;
	int LenExpKey = aes->LenExpKey;
	int Nk = aes->Nk;

	for (j = 0; j < Nk; ++j) { //前Nk个密钥
		w[0][j] = Key[4*j];
		w[1][j] = Key[4*j + 1];
		w[2][j] = Key[4*j + 2];
		w[3][j] = Key[4*j + 3];
	}

	for (; j < LenExpKey / 4; ++j) {
		if (j % Nk == 0) {
			unsigned char temp[4]; //R(wi-1)
			temp[0] = w[1][j-1];
			temp[1] = w[2][j-1];
			temp[2] = w[3][j-1];
			temp[3] = w[0][j-1];

			temp[0] = sBox(temp[0]); //S(R(wi-1))
			temp[1] = sBox(temp[1]);
			temp[2] = sBox(temp[2]);
			temp[3] = sBox(temp[3]);

			w[0][j] = w[0][j-Nk] ^ (temp[0] ^ Rcon[j/Nk]);
			w[1][j] = w[1][j-Nk] ^ (temp[1] ^ 0x00);
			w[2][j] = w[2][j-Nk] ^ (temp[2] ^ 0x00);
			w[3][j] = w[3][j-Nk] ^ (temp[3] ^ 0x00);
		}
		else if (Nk > 6 && (j - 4) % Nk == 0) {
			w[0][j] = w[0][j-Nk] ^ sBox(w[0][j-1]);
			w[1][j] = w[1][j-Nk] ^ sBox(w[1][j-1]);
			w[2][j] = w[2][j-Nk] ^ sBox(w[2][j-1]);
			w[3][j] = w[3][j-Nk] ^ sBox(w[3][j-1]);
		}
		else {
			w[0][j] = w[0][j-Nk] ^ w[0][j-1];
			w[1][j] = w[1][j-Nk] ^ w[1][j-1];
			w[2][j] = w[2][j-Nk] ^ w[2][j-1];
			w[3][j] = w[3][j-Nk] ^ w[3][j-1];
		}
	}
}


static void addRoundKey(PAES_OPERATOR_t aes,int count)
{
	unsigned char (*State)[8] = aes->State;
	unsigned char (*w)[120] = aes->w;
	int Nb = aes->Nb;

	int i, j;
	for (i = 0; i < 4; ++i)
		for (j = 0; j < Nb; ++j)
			State[i][j] = State[i][j] ^ w[i][count * Nb + j];
}

static void byteSub(PAES_OPERATOR_t aes)
{
	unsigned char (*State)[8] = aes->State;
	int Nb = aes->Nb;

	int i, j;
	for (i = 0; i < 4; ++i) //查表进行字节代替
	{
		for (j = 0; j < Nb; ++j) {
			State[i][j] = sBox(State[i][j]);
		}
	}
}

static void shiftRow(PAES_OPERATOR_t aes)
{
	unsigned char (*State)[8] = aes->State;
	int Nb = aes->Nb;

	int c1 = 1, c2, c3;

	//计算轮数
	if (Nb == 4 || Nb == 6) {
		c2 = 2;
		c3 = 3;
	}
	else if (Nb == 8) {
		c2 = 3;
		c3 = 4;
	}
	else {
		printf("Nb 只能为 4、6 或 8 ！");
		return;
	}

	int j, i;
	unsigned char temp[4][8];

	for (i = 1; i < 4; ++i)
		for (j = 0; j < Nb; ++j)
			temp[i][j] = State[i][j];
	for (j = 0; j < Nb; ++j) {//第二行移位c1位
		State[1][j] = temp[1][(j + c1) % Nb];
	}
	for (j = 0; j < Nb; ++j) //第三行移位c2位
		State[2][j] = temp[2][(j + c2) % Nb];
	for (j = 0; j < Nb; ++j) //第四行移位c3位
		State[3][j] = temp[3][(j + c3) % Nb];

}


static void mixColumn(PAES_OPERATOR_t aes)
{
	unsigned char (*State)[8] = aes->State;
	int Nb = aes->Nb;

	int j, i;
	unsigned char MC[4][4] = {{0x02, 0x03, 0x01, 0x01},
							  {0x01, 0x02, 0x03, 0x01},
						      {0x01, 0x01, 0x02, 0x03},
							  {0x03, 0x01, 0x01, 0x02}};
	unsigned char column[4];

	for (j = 0; j < Nb; ++j) { //对每一列进行乘矩阵MC的操作
		for (i = 0; i < 4; ++i)
			column[i] = State[i][j];
		for (i = 0; i < 4; ++i)
			State[i][j] = mul(MC[i][0], column[0]) ^ mul(MC[i][1], column[1]) ^ mul(MC[i][2], column[2]) ^ mul(MC[i][3], column[3]);
	}
}

static void round(PAES_OPERATOR_t aes,int count) //加密时的一轮迭代
{
	byteSub(aes);
	shiftRow(aes);
	mixColumn(aes);
	addRoundKey(aes,count + 1);
}

static void finalRound(PAES_OPERATOR_t aes) //加密时的最后一轮迭代
{
	byteSub(aes);
	shiftRow(aes);
	addRoundKey(aes,aes->RoundNum);
}






//======================================================解密过程所需函数定义
static void inv_addRoundKey(PAES_OPERATOR_t aes,int count)
{
	unsigned char (*State)[8] = aes->State;
	unsigned char (*w)[120] = aes->w;
	int Nb = aes->Nb;
	int RoundNum = aes->RoundNum;

	int inv_count = RoundNum - count;
	int i, j;
	for (i = 0; i < 4; ++i)
		for (j = 0; j < Nb; ++j)
			State[i][j] = State[i][j] ^ w[i][inv_count * Nb + j];
}

static void inv_byteSub(PAES_OPERATOR_t aes)
{
	unsigned char (*State)[8] = aes->State;
	int Nb = aes->Nb;

	int i, j;
	for (i = 0; i < 4; ++i) //查表进行字节代替
		for (j = 0; j < Nb; ++j) {
			State[i][j] = inv_sBox(State[i][j]);
		}
}



static void inv_shiftRow(PAES_OPERATOR_t aes)
{
	unsigned char (*State)[8] = aes->State;
	int Nb = aes->Nb;

	int c1 = 1, c2, c3;
	//计算轮数
	if (Nb == 4 || Nb == 6) {
		c2 = 2;
		c3 = 3;
	}
	else if (Nb == 8) {
		c2 = 3;
		c3 = 4;
	}
	else {
		printf("Nb 只能为 4、6 或 8 ！");
		return;
	}

	int j, i;
	unsigned char temp[4][8];

	for (i = 1; i < 4; ++i)
		for (j = 0; j < Nb; ++j)
			temp[i][j] = State[i][j];
	for (j = 0; j < Nb; ++j) {//第二行移位c1位
		State[1][j] = temp[1][(j + Nb - c1) % Nb];
	}
	for (j = 0; j < Nb; ++j) //第三行移位c2位
		State[2][j] = temp[2][(j + Nb - c2) % Nb];
	for (j = 0; j < Nb; ++j) //第四行移位c3位
		State[3][j] = temp[3][(j + Nb - c3) % Nb];

}

static void inv_mixColumn(PAES_OPERATOR_t aes)
{
	unsigned char (*State)[8] = aes->State;
	int Nb = aes->Nb;

	int j, i;
	unsigned char MC[4][4] = {{0x0E, 0x0B, 0x0D, 0x09},
							  {0x09, 0x0E, 0x0B, 0x0D},
						      {0x0D, 0x09, 0x0E, 0x0B},
							  {0x0B, 0x0D, 0x09, 0x0E}};
	unsigned char column[4];

	for (j = 0; j < Nb; ++j) { //对每一列进行乘矩阵MC的操作
		for (i = 0; i < 4; ++i)
			column[i] = State[i][j];
		for (i = 0; i < 4; ++i)
			State[i][j] = mul(MC[i][0], column[0]) ^ mul(MC[i][1], column[1]) ^ mul(MC[i][2], column[2]) ^ mul(MC[i][3], column[3]);
	}
}


static void inv_round(PAES_OPERATOR_t aes,int count) //解密过程的一轮迭代
{
	inv_shiftRow(aes);
	inv_byteSub(aes);
	inv_addRoundKey(aes,count + 1);
	inv_mixColumn(aes);
}

static void inv_finalRound(PAES_OPERATOR_t aes)  //解密过程的最后一轮迭代
{
	inv_shiftRow(aes);
	inv_byteSub(aes);
	inv_addRoundKey(aes,aes->RoundNum);
}

//=======================================================对外公开接口

void aes_init(PAES_OPERATOR_t aes,const void* pKey,U8 key_len,U8 uBlockLen)
{
	const U8* key = (const U8*)pKey;

	aes->LenText = uBlockLen;
	aes->LenKey = key_len;
	aes->Nb = aes->LenText / 4;
	aes->Nk = aes->LenKey / 4;
	if (aes->Nb == 8 || aes->Nk == 8)
		aes->RoundNum = 14;
	else if (aes->Nb == 6 || aes->Nk == 6)
		aes->RoundNum = 12;
	else
		aes->RoundNum = 10;

	aes->LenExpKey = (1 + aes->RoundNum) * aes->LenText;

	//初始化明文文本PlainText
	int i, j, k;
//	for (i = 0; i < 4; ++i)
//	{
//		for (j = 0; j < Nb; ++j) {
//			k = 4 * j + i;
//			Plaintext[i][j] = plain[k];
//			State[i][j] = plain[k];
//		}
//	}

	//初始化密钥
	for (i = 0; i < aes->LenKey; ++i) {
		aes->Key[i] = key[i];
	}

	KeyExpansion(aes);
}



void aes_encrypt(PAES_OPERATOR_t aes,const void* pPlain,void* pCipher) //加密
{
	//memcpy(State,pPlain,LenText);
	const U8 * plain = (const U8*)pPlain;
	U8* cipher = (U8*)pCipher;

	unsigned char (*State)[8] = aes->State;
	int Nb = aes->Nb;
	int RoundNum = aes->RoundNum;

	int i, j, k;
	for (i = 0; i < 4; ++i)
	{
		for (j = 0; j < Nb; ++j) {
			k = 4 * j + i;
			//Plaintext[i][j] = pPlain[k];
			State[i][j] = plain[k];
		}
	}

	addRoundKey(aes,0);
	for (i = 0; i < RoundNum - 1; ++i)
		round(aes,i);
	finalRound(aes);

	//memcpy(pCipher,State,LenText);
//	for (i = 0; i < 4; ++i)
//		for (j = 0; j < Nb; ++j)
//			Ciphertext[i][j] = State[i][j];

	for (j = 0; j < Nb; ++j)
		for (i = 0; i < 4; ++i)
			cipher[4*j + i] = State[i][j];
}



void aes_decrypt(PAES_OPERATOR_t aes,const void* pCipher,void* pPlain)  //解密
{
	const U8* cipher = (const U8*)pCipher;
	U8* plain = (U8*)pPlain;

	unsigned char (*State)[8] = aes->State;
	int Nb = aes->Nb;
	int RoundNum = aes->RoundNum;

	int i, j,k;

	//memcpy(State,pCipher,LenText);
	for (i = 0; i < 4; ++i)
		for (j = 0; j < Nb; ++j) {
			k = 4 * j + i;
			State[i][j] = cipher[k];
		}


	inv_addRoundKey(aes,0);
	for (i = 0; i < RoundNum - 1; ++i)
		inv_round(aes,i);
	inv_finalRound(aes);

	for (j = 0; j < Nb; ++j)
		for (i = 0; i < 4; ++i)
			plain[4*j + i] = State[i][j];
}




























